package com.lysj.bhp.manager.base;


import com.google.common.util.concurrent.RateLimiter;
import com.lysj.bhp.app.base.AppContent;
import com.lysj.bhp.log.note.SystemLog;
import com.lysj.bhp.log.service.SystemLogAspect;
import com.lysj.bhp.manager.domain.Staff;
import com.lysj.bhp.manager.repository.StaffRepository;
import com.lysj.bhp.system.service.IpRecordService;
import com.lysj.bhp.user.base.UserContent;
import com.lysj.bhp.user.domain.User;
import com.lysj.bhp.user.repository.UserRepository;
import com.lysj.bhp.util.json.JacksonUtil;
import com.lysj.bhp.util.signature.SignatureUtil;
import com.lysj.bhp.util.web.ParamUtil;
import com.lysj.bhp.util.web.Resp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter;
import org.springframework.util.Assert;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.Map;
import java.util.TreeMap;

@Configuration
public class ManagerInterceptor extends UserContent {


    @Resource
    private StaffRepository staffRepository;
    @Resource
    private UserRepository userRepository;
    @Resource
    private IpRecordService ipRecordService;
    @Resource
    private SystemLogAspect systemLogAspect;

    private final Logger logger = LoggerFactory.getLogger(ManagerInterceptor.class);


    private static final RateLimiter RATE_LIMITER = RateLimiter.create(10);

    @Override
    public void addInterceptors(InterceptorRegistry registry) {


        registry.addInterceptor(new HandlerInterceptorAdapter() {

            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                // 允许跨域的配置
                response.addHeader("Access-Control-Allow-Origin", "*");
                response.addHeader("Access-Control-Allow-Methods", "*");
                response.addHeader("Access-Control-Max-Age", "100");
                response.addHeader("Access-Control-Allow-Headers", "Content-Type");
                response.addHeader("Access-Control-Allow-Credentials", "false");
                response.setCharacterEncoding("UTF-8");

                String remoteIP = request.getRemoteAddr();// 请求IP
                String URL = request.getRequestURI();
                //IP频率限制
//                if (!ipRecordService.verifyIp(remoteIP)) {
//                    logger.info("拦截器[" + remoteIP + "]-->" + URL + "-->拦截[访问频率过高]{staff模块}");
//                    return false;
//                }
//
//                System.out.println(remoteIP + "-----");
//                boolean flag = ipRecordService.verifyIp(remoteIP);
//                System.out.println(flag);
                // /////////放行一些固定有的权限///////////////
                if (URL.startsWith("/error") || URL.startsWith("/dividend")) {
                    logger.info("拦截器[" + remoteIP + "]-->" + URL + "-->放行[无需验证权限]{error}");
                    return true;
                }
                if (URL.startsWith("/swagger") || URL.startsWith("/v2")|| URL.startsWith("/test")) {
                    logger.info("拦截器[" + remoteIP + "]-->" + URL + "-->放行[无需验证权限]{swagger}");
                    return true;
                }
                if (URL.startsWith("/pub")) {
                    logger.info("拦截器[" + remoteIP + "]-->" + URL + "-->放行[无需验证权限]{pub}");
                    return true;
                }
                if (URL.startsWith("/api/v1")) {
                    if (!RATE_LIMITER.tryAcquire()) {
                        response.getWriter().write("{\"code\": 403 ,\"msg\":\"嘿,兄弟,你太快啦,有点受不了呀\"}");
                        logger.error("拦截器[" + remoteIP + "]-->" + URL + "-->拦截[访问速率过高]{api}");
                        return false;
                    }
                    logger.info("拦截器[" + remoteIP + "]-->" + URL + "-->放行[无需验证权限]{api}");
                    return true;
                }
                if (URL.startsWith("/admin/staff/login") || URL.startsWith("/admin/staff/isLogin") || URL.startsWith("/admin/staff/quit")) {
                    logger.info("拦截器[" + remoteIP + "]-->" + URL + "-->放行[无需验证权限]{staff模块}");
                    return true;
                }
                if (URL.startsWith("/admin/exchange_rate/rates")) {
                    logger.info("拦截器[" + remoteIP + "]-->" + URL + "-->放行[无需验证权限]{exchange_rate模块}");
                    return true;
                }

                String token = request.getParameter("token");

                // 用户模块
                if (URL.startsWith("/api/v2/user/")) {
                    if (URL.startsWith("/api/v2/user/login") || URL.startsWith("/api/v2/user/isLogin")
                            || URL.startsWith("/api/v2/user/quit") || URL.startsWith("/api/v2/user/regist") || URL.startsWith("/api/v2/user/users/")
                            || URL.startsWith("/api/v2/user/reset_password") || URL.startsWith("/api/v2/user/active") || URL.startsWith("/api/v2/user/bcex")
                            || URL.startsWith("/api/v2/user/verify") || URL.startsWith("/api/v2/user/forget_password") || URL.startsWith("/api/v2/user/get_all_announce")
                            || URL.startsWith("/api/v2/user/get_all_article") || URL.startsWith("/api/v2/user/show_announcement_detail") || URL.startsWith("/api/v2/user/show_article_detail")
                            || URL.startsWith("/api/v2/user/activity_list") || URL.startsWith("/api/v2/user/show_activity_detail")|| URL.startsWith("/api/v2/user/show_slideshow_detail")
                            || URL.startsWith("/api/v2/user/phone_login") || URL.startsWith("/api/v2/user/get_my_email_verify_code") || URL.startsWith("/api/v2/user/phone_reset_password") || URL.startsWith("/api/v2/user/send_verify_code")) {
                        logger.info("拦截器[" + remoteIP + "]-->" + URL + "-->放行[无需验证权限]{user模块}");
                        return true;
                    }
                    if (ParamUtil.isBlack(token)) {
                        response.getWriter().write("{\"code\": 422 ,\"msg\":\"Token Invalid\"}");
                        return false;
                    }
                    User user = userRepository.findByToken(token);
                    if (user == null || System.currentTimeMillis() > user.getExpires()) {// 校验token是否正确
                        logger.info("拦截器[" + remoteIP + "]-->" + URL + "-->拦截[Token Invalid]");
                        response.getWriter().write("{\"code\": 422 ,\"msg\":\"Token Invalid\"}");
                        return false;
                    }

//                    if (null != user.getLastAddress()&& user.getLastAddress().equals(URL)) {
//                        if (System.currentTimeMillis() < user.getNextRequestTime()) {
//                            logger.info("拦截器[" + remoteIP + "]-->" + URL + "-->拦截[访问频率过高]");
//                            response.getWriter().write("{\"code\": 422 ,\"msg\":\"您的访问频率过高\"}");
//                            return false;
//                        }else {
//                            user.setNextRequestTime(System.currentTimeMillis() + REQUEST_EXPIRES_USER);
//                            user.setLastAddress(URL);
//                        }
//                    }
//                    user.setNextRequestTime(System.currentTimeMillis() + REQUEST_EXPIRES_USER);
//                    user.setLastAddress(URL);
//                    userRepository.save(user);
                    request.setAttribute("user", user);
                    logger.info("拦截器[" + remoteIP + "]-->" + URL + "-->放行[Token正确]");
                    return true;
                }

                // 开始校验管理员模块///////////////////////

                if (URL.startsWith("/admin/")) {
                    Staff staff = staffRepository.findByToken(token);
                    if (staff == null || System.currentTimeMillis() > staff.getExpires()) {// 校验token是否正确

                        logger.info("拦截器[" + remoteIP + "]-->" + URL + "-->拦截[Token Invalid]");
                        response.getWriter().write("{\"code\": 422 ,\"msg\":\"Token Invalid\"}");
                        return false;
                    }
                    request.getSession().setAttribute("staff", staff);
                    request.setAttribute("staff", staff);
                    logger.info("拦截器[" + remoteIP + "]-->" + URL + "-->放行[Token正确]");
                    return true;
                }


                // 开始校验调用钱包接口方法模块///////////////////////

                if (URL.startsWith("/api/balance/wallet/")) {

                    if (!checkSignature(request, AppContent.CODE)) { // 校验签名是否正确
                        logger.error("Signature error");
                        response.getWriter().write("{\"code\":422,\"msg\":\"Signature error\"}");
                        return false;
                    }
                    return true;
                }
                //第三方
                if (URL.startsWith("/api/tpos/v1/public/")) {
                    String appId=  request.getParameter("appId");
                    //通过appid查询对应得code
                    boolean result = true;
                    if (!checkSignature(request, AppContent.information.get(appId))) { // 校验签名是否正确
                        logger.error("Signature error");
                        response.getWriter().write("{\"code\":422,\"msg\":\"Signature error\"}");
                        result = false;
                        systemLogAspect.addTposLog("签名校验失败",result,System.currentTimeMillis());
                    }
                    return result;
                }
                ///////////结束权限校验///////////////
                return false;
            }

        }).addPathPatterns("/**");

    }

    // 校验签名是否正确
    private boolean checkSignature(HttpServletRequest request, String code) {

        String signature = request.getParameter("signature");

        Enumeration<String> keys = request.getParameterNames();
        Map<String, String> paramMap = new TreeMap<>();
        while (keys.hasMoreElements()) { // 获取所有参数,并排序
            String key = keys.nextElement();
            logger.debug("本次请求的参数 : " + key + ":" + request.getParameter(key));
            if (!"".equals(key) && !"signature".equals(key)) { // 非空且不等于signature
                paramMap.put(key, request.getParameter(key));
            }
        }
        StringBuilder paramBuilder = new StringBuilder();
        paramMap.forEach((k, v) -> {
            paramBuilder.append(k).append("=").append(v).append("&");
        });
        paramBuilder.append("code=").append(code);
        String paramStr = paramBuilder.toString();
        logger.debug("signature param string -> " + paramStr);
        String paramSignature = SignatureUtil.md5(paramStr);
        logger.debug("signature result string -> " + paramSignature);
        logger.info("signature result string -> " + paramSignature);
        return paramSignature != null && paramSignature.equals(signature);
    }


}
